package com.yyge.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yyge.callback.List2ListVoCallback;
import com.yyge.callback.PageCallback;
import com.yyge.callback.QueryCallback;
import com.yyge.dto.Query;
import com.yyge.system.entity.SystemUser;
import com.yyge.util.AuthUtil;
import com.yyge.vo.PageVo;
import com.yyge.util.FieldUtil;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * BaseController
 * @param <T> 实体类
 * @param <R> 普通返回类型 Vo - 用于分页查询等
 * @param <D> Detail 返回实体类型 Vo - 用于详情数据查询返回
 */
public class BaseController<T,R,D> {

    @Autowired
    private AuthUtil authUtil;

    @Autowired
    private FieldUtil fieldUtil;

    /**
     * 获取当前的类的Wrapper对象 也就是QueryWrapper对象
     * @param object 转换后的实体类
     * @return 返回 QueryWrapper
     * @throws Exception 反射会用到的可能会报错 所以要处理异常
     */
    public QueryWrapper<T> getWrapper(Object object) throws Exception {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        //判断如果传进来的对象
        System.out.println(object.getClass().getName());
        //获取实体所有对应的列
        Map<String, ColumnCache> columnMap = LambdaUtils.getColumnMap(object.getClass());
        System.out.println(columnMap);
        for (Field field : fieldUtil.getFieldNames(object)) {
            Class<?> Obj = object.getClass();

            if (field.getType().equals(String.class)) {
                String MethodName = "get" + (field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1));

                // 获取方法
                Method method = Obj.getMethod(MethodName);
                // 调用方法
                Object result = method.invoke(object);
                String column = columnMap.get(LambdaUtils.formatKey(field.getName())).getColumn();
                wrapper.like(column, result);
            }
        }
        return wrapper;
    }

    /**
     * 将接收的Query对象 转化为对应的Page对象 这个page是查询后的page内含数据
     * @param query 查询对象
     * @callbackcallback 回调函数
     * @return Page<T> 泛型需要指定
     */
    public Page<T> query2Page(QueryWrapper<T> wrapper,Query query,QueryCallback<T> callback) throws Exception  {
        Page<T> page = new Page<>();
        if (Objects.nonNull(query)){
            page.setSize(query.getSize()==null?10:query.getSize());
            page.setCurrent(query.getCurrent()==null?0: query.getCurrent());
        }
        return callback.doPage(page,wrapper);
    }

    /**
     * 该函数将Page对象转换为PageVo对象 其中的entity也会转化为vo
     * @param page 含有数据的page对象
     * @param callback 函数式接口 提供两个泛型 T为当前实体类对象 R为返回对象类型
     * @return PageVo R为返回实体类型的对象
     */
   public PageVo<R> page2PageVo(Page<T> page,List2ListVoCallback<T,R> callback){
       List<R> list = callback.doConvert(page.getRecords());
       PageVo<R> pageVo = new PageVo<>();
       pageVo.setPageSize(Integer.parseInt(page.getSize()+""));
       pageVo.setPageNum(Integer.parseInt(page.getCurrent()+""));
       pageVo.setTotal(page.getTotal());
       pageVo.setRows(list);
       return pageVo;
   }

    /**
     * 获取当前用户 在controller里面通过this获取
     * @return 返回SystemUser对象
     */
   public SystemUser getUser(){
       SystemUser user = authUtil.getUser();
       Optional.ofNullable(user).orElseThrow(()->new RuntimeException("登录账户异常,请退出后重试"));
       return user;
   }

    /**
     * 添加 用户权限 - 针对于创建用户 传入wrapper
     * 帮你进行鉴权并且添加 创建CreateUser的条件
     * @return 返回布尔值
     */
   public QueryWrapper<T> addAuth(QueryWrapper<T> wrapper){
       SystemUser user = authUtil.getUser();
       Optional.ofNullable(user).orElseThrow(()->new RuntimeException("登录账户异常,请退出后重试"));
       if(user.getAccountType()!=9){
           wrapper.eq("create_user",user.getId());
           return wrapper;
       }
       return wrapper;
   }

    public PageVo<?> page(Page<T> page, PageCallback<T> callback){
        Page<T> pageInfo = callback.doPage(page);
//        BeanConverter.MAPPER.page2vo(pageInfo)
        return null;
    }
}
